package simplechat;

// This file contains material supporting section 3.7 of the textbook:
// "Object Oriented Software Engineering" and is issued under the open-source
// license found at www.lloseng.com

import java.io.*;
import ocsf.server.*;
import java.util.*;
/**
 * This class overrides some of the methods in the abstract
 * superclass in order to give more functionality to the server.
 *
 * @author Dr Timothy C. Lethbridge
 * @author Dr Robert Lagani&egrave;re
 * @author Fran&ccedil;ois B&eacute;langer
 * @author Paul Holden
 * @version July 2000
 */
public class EchoServer extends AbstractServer
{
  //Class variables *************************************************

  /**
   * The default port to listen on.
   */
  final public static int DEFAULT_PORT = 5555;
  private HashMap users;
  private List ingelogd;

  //Constructors ****************************************************

  /**
   * Constructs an instance of the echo server.
   *
   * @param port The port number to connect on.
   */
  public EchoServer(int port)
  {
    super(port);
    this.users = new HashMap<String, String>();
    this.ingelogd = new ArrayList<ConnectionToClient>();
  }
  //Functie die een username of password controlleert
  public boolean checkString(String str)
  {
	  if (str.length() > 20 || str.length() < 3) {return false;}
	  return true;
  }
  //Instance methods ************************************************

  /**
   * This method handles any messages received from the client.
   *
   * @param msg The message received from the client.
   * @param client The connection from which the message originated.
   */
  public void handleMessageFromClient (Object msg, ConnectionToClient client)
  { 
	String[] split =  ((String) msg).split(" ");
	
	try {
	//Nieuwe gebruiker wil registreren
	if (split[0].equals("#register") && split.length >= 3 && !ingelogd.contains(client))
	{
		String username = split[1];
		String password = split[2];
		
		if(!checkString(username) || !checkString(password))
		{
			client.sendToClient("Username en of wachtwoord voldoen niet aan de eisen. \n Gebruikersnaam en wachtwoord moeten meer dan 3 en minder dan 20 karakters bevatten en mogen ook geen spaties bevatten!");
		} else if(users.get(username) != null){
			client.sendToClient("Username bestaat al. Kies een andere username of log in!");
		} else {
			this.users.put(username, password);
			this.ingelogd.add(client);
			client.setInfo("username", username);
			client.setInfo("loggedon", true);
			client.sendToClient("U bent geregistreerd en ingelogd.");
			sendToLoggedInClients((String)client.getInfo("username") + " is ingelogd");
		}
	//Gebruiker wil inloggen	
	} else if (split[0].equals("#login") && !ingelogd.contains(client))
	
	{
		if (split.length < 3 || this.users.get(split[1]) == null || !this.users.get(split[1]).equals(split[2]))
		{
			//Wachtwoord fout
			client.sendToClient("U dient een geldige username en password mee te geven: #login <username> <password>");
		} else {
			//Wachtwoord goed
			client.setInfo("username", split[1]);
			client.setInfo("loggedon", true);
			this.ingelogd.add(client);
			client.sendToClient("U bent ingelogd.");
			sendToLoggedInClients((String)client.getInfo("username") + " is ingelogd");
		}	
	} else if(this.ingelogd.contains(client)) {
		
	// Het is een bericht en dit moet verstuurd worden aan iedereen die ingelogd is.
		sendToLoggedInClients((String)client.getInfo("username") + " zegt: " + msg);
		
	} else {
		client.sendToClient("Foutief invoer; u bent niet ingelogd. Registreer met #register <gebruikersnaam> <wachtwoord> of login met #login <gebruikersnaam> <wachtwoord>!");
	}
	} catch (IOException e) {System.out.println("IO Exception!");}
  }

  /**
   * This method overrides the one in the superclass.  Called
   * when the server starts listening for connections.
   */
  protected void serverStarted()
  {
    System.out.println
      ("Server listening for connections on port " + getPort());
  }

  /**
   * This method overrides the one in the superclass.  Called
   * when the server stops listening for connections.
   */
  protected void serverStopped()
  {
    System.out.println
      ("Server has stopped listening for connections.");
  }

  //Class methods ***************************************************

  /**
   * This method is responsible for the creation of
   * the server instance (there is no UI in this phase).
   *
   * @param args[0] The port number to listen on.  Defaults to 5555
   *          if no argument is entered.
   */
  public static void main(String[] args)
  {
    int port = 0; //Port to listen on

    try
    {
      port = Integer.parseInt(args[0]); //Get port from command line
    }
    catch(Throwable t)
    {
      port = DEFAULT_PORT; //Set port to 5555
    }

    EchoServer sv = new EchoServer(port);

    try
    {
      sv.listen(); //Start listening for connections
    }
    catch (Exception ex)
    {
      System.out.println("ERROR - Could not listen for clients!");
    }
  }
  
  
  protected void clientConnected(ConnectionToClient client)
  {
	try {
	client.sendToClient("Welkom! Registreer met #register <gebruikersnaam> <wachtwoord> of login met #login <gebruikersnaam> <wachtwoord>!");
  	System.out.println(client.toString() + " heeft een verbinding met de server gestart :).");
	} catch(IOException e) {}
  }
  
    synchronized protected void clientDisconnected(ConnectionToClient client) 
    {
    	System.out.println(client.getInfo("username") + " heeft de verbinding met de server verbroken :(.");
    	
    }
    
   synchronized protected void clientException(ConnectionToClient client, Throwable exception) {
   	System.out.println(client.getInfo("username") + " heeft de verbinding met de server verbroken :((.");
   	ingelogd.remove(client);

   	sendToLoggedInClients((String)client.getInfo("username") + " heeft de verbinding verbroken!");
   }
   
   //stuurt een bericht naar alle ingelogde gebruikers.
   private void sendToLoggedInClients(String msg) {
	   try{
		   for (int i=0; i < this.ingelogd.size(); i++)
		   {
			   ((ConnectionToClient)(this.ingelogd.get(i))).sendToClient(msg);
		   }
	   	} catch( IOException e) {System.out.println("IO Exception!")}
   }
}
//End of EchoServer class
